package cn.mengfly.testnrz.crazyIm.webserver;

import cn.mengfly.testnrz.crazyIm.ServerConstants;
import cn.mengfly.testnrz.crazyIm.nettyserver.ImNode;
import cn.mengfly.testnrz.curator.ZkClient;
import cn.mengfly.testnrz.json.JsonUtil;
import org.apache.curator.framework.CuratorFramework;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 负载均衡
 *
 * @author Mengfly
 */
public class ImLoadBalance {

    private CuratorFramework client = null;
    private String managerPath;

    public ImLoadBalance() {

    }

    public ImLoadBalance(String managerPath) {
        this.client = ZkClient.inst().getClient();
        this.managerPath = managerPath;
    }

    public static final ImLoadBalance INSTANCE = new ImLoadBalance(ServerConstants.MANAGE_PATH);


    /**
     * 获取负载最小的IM节点
     */
    public ImNode getBestWorker() {
        List<ImNode> workers = getWorkers();
        return balance(workers);
    }

    /**
     * 负载均衡算法：根据负载进行排序
     *
     * @param items 所有的Netty服务器节点
     * @return 负载均衡算法挑选出的最优节点
     */
    protected ImNode balance(List<ImNode> items) {
        if (items.size() > 0) {
            // 根据 balance 值从小到大排序
            Collections.sort(items);
            return items.get(0);
        } else {
            return null;
        }
    }

    /**
     * 从Zookeeper 中拿到所有的IM节点
     *
     * @return IM服务器节点列表
     */
    protected List<ImNode> getWorkers() {
        List<ImNode> workers = new ArrayList<>();
        List<String> children;
        try {
            children = client.getChildren().forPath(managerPath);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        for (String child : children) {
            byte[] payload = null;
            try {
                payload = client.getData().forPath(child);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (null == payload) {
                continue;
            }
            ImNode worker = JsonUtil.jsonBytes2Object(payload, ImNode.class);
            workers.add(worker);
        }
        return workers;
    }

}
